#include <iostream>
#include <functional>
#include <memory>
#include <unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
private:
    uint64_t _id;         // 定时器任务对象id
    uint32_t _timeout;    // 定时任务的超时时间
    TaskFunc _task_cb;    // 定时器对象要执行的定时任务
    ReleaseFunc _release; // 用于删除TImerWheel中保存的定时器对象信息
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb)
        : _id(id), _timeout(delay), _task_cb(cb) {}

    ~TimerTask()
    {
        _task_cb();
        _release();
    }

    // 设置release回调
    void SetRelease(const ReleaseFunc &cb) { _release = cb; }
    uint32_t DelayTime() { return _timeout; }
};

using PtrTask = std::shared_ptr<TimerTask>;
using WeakTask = std::weak_ptr<TimerTask>;
class TimerWheel
{
private:
    int _tick;                                      // 滴答指针，走到那里就释放那里，相当于当前执行哪里的任务
    int _capacity;                                  // 时间轮的最大数量  相当于最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;       // 时间轮 里面存放的是shared_ptr管理的定时器任务
    std::unordered_map<uint64_t, WeakTask> _timers; // 用于管理时间轮中的定时器任务，使用的是Weak_ptr
private:
    // 移除_timers中的定时器任务信息
    void RemoveTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it != _timers.end())
        {
            _timers.erase(it);
        }
    }

public:
    TimerWheel() : _capacity(60), _tick(0), _wheel(_capacity) {}
    ~TimerWheel() {}

    // 添加定时器任务
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)
    {
        PtrTask pt(new TimerTask(id, delay, cb));
        // 绑定定时器任务pt的release回调函数
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        // 拷贝构造了一个Weak_ptr的pt对象插入_timers中
        _timers[id] = WeakTask(pt);
    }

    // 延迟or刷新定时任务 延迟时间为定时器任务中设置的_timeout时间
    void TimerRefresh(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return; // 没找着任务，么办法刷新
        }

        PtrTask pt = it->second.lock(); // lock返回一个weak_ptr管理对象的一个Shared_ptr指针
        int delay = pt->DelayTime();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        std::cout<<"延迟成功"<<std::endl;
    }

    // 这个函数每秒钟被执行依次，滴答指针就会向后移动一位
    void RunTimerTask()
    {
        //_tick向后移动一位
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear(); // 清空指定位置的数组，就会把数组中的shared_ptr释放掉
    }
};

class Test
{
public:
    Test() { std::cout << "构造" << std::endl; }

    ~Test() { std::cout << "析构" << std::endl; }
};

void func(Test *t)
{
    delete t;
}

int main()
{
    TimerWheel tw;

    Test *t = new Test();
    tw.TimerAdd(888, 5, std::bind(func, t));
    //走三秒在延迟
    for(int i=0;i<3;i++)
    {
        tw.RunTimerTask();
        sleep(1);

    }
    tw.TimerRefresh(888);   //延迟5秒
    while(1)
    {
        std::cout<<"---------"<<std::endl;
        tw.RunTimerTask();
        sleep(1);
    }
    return 0;
}